package io.kimmking.rpcfx.demo.consumer.aop;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import io.kimmking.rpcfx.api.RpcfxRequest;
import io.kimmking.rpcfx.api.RpcfxResponse;
import io.kimmking.rpcfx.client.NettyHttpClient;
import io.kimmking.rpcfx.demo.api.RpcfxException;
import io.kimmking.rpcfx.demo.api.User;
import io.kimmking.rpcfx.demo.api.UserService;
import io.kimmking.rpcfx.demo.api.util.StringCompress;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.matcher.ElementMatchers;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import static net.bytebuddy.matcher.ElementMatchers.any;

@Aspect
@Component
public class Aop {

    @Pointcut(value="execution(* io.kimmking.rpcfx.demo.consumer.impl.*ServiceImpl.*(..))")
    public void point(){

    }

//    @Before(value="point()")
//    public void before(){
//        System.out.println("========>begin aop2...");
//    }
//
//    @AfterReturning(value = "point()")
//    public void after(){
//        System.out.println("========>after aop2...");
//    }

    @Around("point()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
//        System.out.println("    ====>around before aop1:" + joinPoint.toShortString()); //1
        RpcfxRequest request = new RpcfxRequest();
        request.setServiceClass(joinPoint.getTarget().getClass().getInterfaces()[0].getName());
        request.setMethod(joinPoint.getSignature().getName());
        request.setParams(joinPoint.getArgs());
        String result = new NettyHttpClient(8080, "localhost", request).post();
        RpcfxResponse response = JSON.parseObject(result, RpcfxResponse.class);
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method m = ms.getMethod();
//        System.out.println("    ====>around after aop1:" + joinPoint.toShortString()); //3
        if (!response.isStatus()) {
            throw new RpcfxException(response.getMessage());
        }
        // 使用gzip对结果解压
        return JSON.parseObject(StringCompress.uncompress(response.getResult().toString()), m.getReturnType());

    }

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, IOException {
        DynamicType.Unloaded unloadedType = new ByteBuddy()
                .subclass(Object.class)
                .method(ElementMatchers.isToString())
                .intercept(FixedValue.value("aaaaaaaaaaaaaa"))
                .make();
        Class<?> dynamicType = unloadedType.load(Aop.class
                .getClassLoader())
                .getLoaded();
        System.out.println(dynamicType.newInstance().toString());

    }
}
